using BunnyEater.Common.ResponseOutput;
using BunnyEater.Domain.Base;
using BunnyEater.Domain.Traceable;
using BunnyEater.EntityFrameworkCore;
using BunnyEater.Repository.BaseRepository;
using BunnyEater.Repository.Extensions;
using BunnyEater.Service.TraceableService.MaterialService.Dto;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;
using System.Threading.Tasks;

namespace BunnyEater.Service.TraceableService.MaterialService
{
    /// <summary>
    /// 物料服务实现，处理物料相关的业务逻辑
    /// </summary>
    public class MaterialService : IMaterialService
    {
        private readonly BunnyEaterContext _bunnyEaterContext;
        private readonly IRepository<Material> _materialRepository;
        private readonly ILogger<MaterialService> _logger;

        public MaterialService(BunnyEaterContext bunnyEaterContext, IRepository<Material> materialRepository, ILogger<MaterialService> logger)
        {
            _bunnyEaterContext = bunnyEaterContext;
            _materialRepository = materialRepository;
            _logger = logger;
        }

        /// <summary>
        /// 分页获取物料列表
        /// </summary>
        /// <param name="query">分页查询参数</param>
        /// <returns>物料分页数据</returns>
        public async Task<ResponseReturnsEntity<Page<MaterialListDto>>> GetPagedMaterialsAsync(MaterialPagedQueryDto query)
        {
            try
            {
                var materials = _materialRepository.GetListQuery().Where(m => !m.IsDelete);
                if (!string.IsNullOrEmpty(query.CommodityName))
                {
                    materials = materials.Where(m => EF.Functions.Like(m.CommodityName, $"%{query.CommodityName}%"));
                }
                var result = await materials.ToPagedListAsync(
                    query.PageIndex,
                    query.PageSize,
                    null,
                    m => m.CreateTime,
                    false);
                var dtoPage = new Page<MaterialListDto>
                {
                    Items = result.Items.Select(m => new MaterialListDto
                    {
                        Id = m.Id,
                        CommodityName = m.CommodityName,
                        ProductionNo = m.ProductionNo,
                        Shelflife = m.Shelflife,
                        ProdLicense = m.ProdLicense,
                        ProdCompanieId = m.ProdCompanieId,
                        CreateTime = m.CreateTime
                    }).ToList(),
                    PageNumber = result.PageNumber,
                    PageSize = result.PageSize,
                    TotalPages = result.TotalPages,
                    TotalItems = result.TotalItems
                };
                return ResponseReturnsEntity<Page<MaterialListDto>>.Success(dtoPage);
            }
            catch (Exception ex)
            {
                _logger.LogError($"分页查询物料失败: {ex.Message}");
                return ResponseReturnsEntity<Page<MaterialListDto>>.Fail($"查询失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 新增物料，包含事务处理和异常回滚
        /// </summary>
        /// <param name="dto">物料信息</param>
        /// <returns>操作结果</returns>
        /// <remarks>
        /// 1. 自动为主键Id赋值Guid字符串。
        /// 2. 包含事务处理，失败自动回滚。
        /// 3. 捕获数据库异常和通用异常，记录详细日志。
        /// </remarks>
        public async Task<ResponseReturnsEntity<bool>> AddMaterial(MaterialListDto dto)
        {
            using var transaction = await _bunnyEaterContext.Database.BeginTransactionAsync();
            try
            {
                // 参数校验
                if (dto == null)
                {
                    return ResponseReturnsEntity<bool>.Fail("物料信息不能为空");
                }
                if (string.IsNullOrEmpty(dto.CommodityName))
                {
                    return ResponseReturnsEntity<bool>.Fail("商品名称不能为空");
                }

                var entity = new Material
                {
                    Id = Guid.NewGuid().ToString(),
                    CommodityName = dto.CommodityName,
                    ProductionNo = dto.ProductionNo,
                    Shelflife = dto.Shelflife,
                    ProdLicense = dto.ProdLicense,
                    ProdCompanieId = dto.ProdCompanieId,
                    CreateTime = DateTime.Now
                };
                var result = await _materialRepository.InsertEntityAsync(entity);

                await transaction.CommitAsync();
                return ResponseReturnsEntity<bool>.Success(result > 0);
            }
            catch (DbUpdateException dbEx)
            {
                await transaction.RollbackAsync();
                _logger.LogError($"数据库更新异常，添加物料失败: {dbEx.Message}", dbEx);
                return ResponseReturnsEntity<bool>.Fail("数据库操作异常，添加物料失败，请检查数据有效性或联系管理员。");
            }
            catch (Exception ex)
            {
                await transaction.RollbackAsync();
                _logger.LogError($"添加物料失败: {ex.Message}", ex);
                return ResponseReturnsEntity<bool>.Fail($"添加物料失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 更新物料信息，包含异常处理
        /// </summary>
        /// <param name="dto">物料信息</param>
        /// <returns>操作结果</returns>
        /// <remarks>
        /// 1. 包含参数校验和存在性检查。
        /// 2. 捕获数据库异常和通用异常，记录详细日志。
        /// </remarks>
        public async Task<ResponseReturnsEntity<bool>> UptMaterial(MaterialListDto dto)
        {
            try
            {
                // 参数校验
                if (dto == null)
                {
                    return ResponseReturnsEntity<bool>.Fail("物料信息不能为空");
                }
                if (string.IsNullOrEmpty(dto.Id))
                {
                    return ResponseReturnsEntity<bool>.Fail("物料ID不能为空");
                }
                if (string.IsNullOrEmpty(dto.CommodityName))
                {
                    return ResponseReturnsEntity<bool>.Fail("商品名称不能为空");
                }

                var entity = await _materialRepository.GetEntityByIdAsync(new Material { Id = dto.Id });
                if (entity == null)
                {
                    return ResponseReturnsEntity<bool>.Fail("物料不存在");
                }

                entity.CommodityName = dto.CommodityName;
                entity.ProductionNo = dto.ProductionNo;
                entity.Shelflife = dto.Shelflife;
                entity.ProdLicense = dto.ProdLicense;
                entity.ProdCompanieId = dto.ProdCompanieId;
                entity.ModifyTime = DateTime.Now;

                var result = await _materialRepository.UpdateEntityAsync(entity);
                return ResponseReturnsEntity<bool>.Success(result > 0);
            }
            catch (DbUpdateException dbEx)
            {
                _logger.LogError($"数据库更新异常，更新物料失败: {dbEx.Message}", dbEx);
                return ResponseReturnsEntity<bool>.Fail("数据库操作异常，更新物料失败，请检查数据有效性或联系管理员。");
            }
            catch (Exception ex)
            {
                _logger.LogError($"更新物料失败: {ex.Message}", ex);
                return ResponseReturnsEntity<bool>.Fail($"更新物料失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 删除物料（逻辑删除），包含异常处理
        /// </summary>
        /// <param name="id">物料Id</param>
        /// <returns>操作结果</returns>
        /// <remarks>
        /// 1. 包含参数校验和存在性检查。
        /// 2. 捕获数据库异常和通用异常，记录详细日志。
        /// </remarks>
        public async Task<ResponseReturnsEntity<bool>> DeleteMaterial(string id)
        {
            try
            {
                // 参数校验
                if (string.IsNullOrEmpty(id))
                {
                    return ResponseReturnsEntity<bool>.Fail("物料ID不能为空");
                }

                var entity = await _materialRepository.GetEntityByIdAsync(new Material { Id = id });
                if (entity == null)
                {
                    return ResponseReturnsEntity<bool>.Fail("物料不存在");
                }

                if (entity.IsDelete)
                {
                    return ResponseReturnsEntity<bool>.Fail("物料已被删除，请勿重复操作");
                }

                entity.IsDelete = true;
                entity.ModifyTime = DateTime.Now;

                var result = await _materialRepository.UpdateEntityAsync(entity);
                return ResponseReturnsEntity<bool>.Success(result > 0);
            }
            catch (DbUpdateException dbEx)
            {
                _logger.LogError($"数据库更新异常，删除物料失败: {dbEx.Message}", dbEx);
                return ResponseReturnsEntity<bool>.Fail("数据库操作异常，删除物料失败，请检查数据有效性或联系管理员。");
            }
            catch (Exception ex)
            {
                _logger.LogError($"删除物料失败: {ex.Message}", ex);
                return ResponseReturnsEntity<bool>.Fail($"删除物料失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 根据Id获取物料信息
        /// </summary>
        /// <param name="id">物料Id</param>
        /// <returns>物料信息</returns>
        public async Task<ResponseReturnsEntity<MaterialListDto>> GetMaterialById(string id)
        {
            var entity = await _materialRepository.GetEntityByIdAsync(new Material { Id = id });
            if (entity == null) return ResponseReturnsEntity<MaterialListDto>.Fail("物料不存在");
            var dto = new MaterialListDto
            {
                Id = entity.Id,
                CommodityName = entity.CommodityName,
                ProductionNo = entity.ProductionNo,
                Shelflife = entity.Shelflife,
                ProdLicense = entity.ProdLicense,
                ProdCompanieId = entity.ProdCompanieId,
                CreateTime = entity.CreateTime
            };
            return ResponseReturnsEntity<MaterialListDto>.Success(dto);
        }
    }
}